﻿Imports System.Xml
Imports System.Text
''' <summary>
''' 语法树节点基类
''' </summary>
''' <remarks></remarks>
Public MustInherit Class clsSyntaxNode
    ''' <summary>
    ''' 获得语法树的XML节点
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    MustOverride Function GetXMLElement() As Xml.XmlElement
    ''' <summary>
    ''' 获得COBOL的代码
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    MustOverride Function Convert2Cobol() As List(Of String)
    ''' <summary>
    '''对于这个过程,IF,SELECT,LOOP的注释 
    ''' </summary>
    ''' <remarks></remarks>
    Public CommentList As New List(Of XmlElement)
    ''' <summary>
    '''设置对于这个过程,IF,SELECT,LOOP的注释
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub SetCommentList()
        For Each StrComment As String In GlobalCommentList
            Dim CommentItem As XmlElement = mXmlDocument.CreateElement("COMMENTLIST")
            CommentItem.SetAttribute("TEXT", StrComment)
            CommentList.Add(CommentItem)
        Next
        GlobalCommentList.Clear()
    End Sub
End Class
''' <summary>
''' 标题部节点类
''' </summary>
''' <remarks></remarks>
Public Class IdentificationNode
    Inherits clsSyntaxNode
    ''' <summary>
    ''' 是否为主程序
    ''' </summary>
    ''' <remarks></remarks>
    Public IsMain As Boolean
    ''' <summary>
    ''' 程序名
    ''' </summary>
    ''' <remarks></remarks>
    Public ProgramID As String
    ''' <summary>
    ''' 获得COBOL的代码
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function Convert2Cobol() As List(Of String)
        Dim strCobol As New List(Of String)
        '程序注释
        For Each CommentXMl As XmlElement In CommentList
            strCobol.Add(FormatCOBOLComment(CommentXMl.GetAttribute("TEXT")))
        Next
        strCobol.Add("       IDENTIFICATION                  DIVISION.")
        If IsMain Then
            strCobol.Add("      *OPTIONS(MAIN)")
        Else
            strCobol.Add("      *OPTIONS(SUB)")
        End If
        '程序名
        strCobol.Add("       PROGRAM-ID.                     " & ProgramID & ".")
        '作者名
        strCobol.Add("       AUTHOR.                         " & MyConfig.Author & ".")
        '工具转换时，自动取得系统当前日期
        strCobol.Add("       DATE-WRITTEN.                   " & Format(Now, "yyyy/MM/dd") & ".")
        Return strCobol
    End Function
    ''' <summary>
    ''' 获得语法树的XML节点
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetXMLElement() As XmlElement
        If ProgramID Is String.Empty Then
            Return Nothing
        Else
            Dim mXmlElement As XmlElement
            mXmlElement = mXmlDocument.CreateElement("IDENTIFICATION")
            mXmlElement.SetAttribute("ProgramID", ProgramID)

            Dim mCommentElement As XmlElement
            mCommentElement = mXmlDocument.CreateElement("PROGRAMCOMMENT")

            For Each CommentXML As XmlElement In CommentList
                mCommentElement.AppendChild(CommentXML)
            Next

            mXmlElement.AppendChild(mCommentElement)

            Return mXmlElement
        End If
    End Function
End Class
''' <summary>
''' 环境部节点类
''' </summary>
''' <remarks></remarks>
Public Class EnvironmentNode
    Inherits clsSyntaxNode
    ''' <summary>
    ''' 文件定义
    ''' </summary>
    ''' <remarks></remarks>
    Public FileList As New List(Of XmlElement)
    ''' <summary>
    ''' PL1 Convert To COBOL
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function Convert2Cobol() As List(Of String)
        '参考文档：定义部和环境部
        Dim strCobol As New List(Of String)
        strCobol.Add("       ENVIRONMENT                     DIVISION.")
        strCobol.Add("       CONFIGURATION                   SECTION.")
        '编译计算机名称
        If MyConfig.SOURCEComputerName <> String.Empty Then
            strCobol.Add("       SOURCE-COMPUTER.                " & MyConfig.SOURCEComputerName & ".")
        End If
        '目标计算机名称
        If MyConfig.OBJECTComputerName <> String.Empty Then
            strCobol.Add("       OBJECT-COMPUTER.                " & MyConfig.OBJECTComputerName & ".")
        End If
        If FileList.Count > 0 Then
            strCobol.Add("       INPUT-OUTPUT                    SECTION.")
            strCobol.Add("       FILE-CONTROL.")
            For Each mFile As XmlElement In FileList
                'SYSPRINT，PRINT型的，可以不定义
                If Not (mFile.GetAttribute("ISPRINT") = "True" And mFile.GetAttribute("FILENAME") = "SYSPRINT") Then
                    If MyConfig.IsCreateFileStatus Then
                        strCobol.Add("           SELECT  " & Mid(mFile.GetAttribute("FILENAME") + Space(20), 1, 20) & "ASSIGN  TO  " & mFile.GetAttribute("FILENAME"))
                        strCobol.Add("              FILE  STATUS  IS  " & mFile.GetAttribute("FILENAME") & "-ST" & ".")
                    Else
                        strCobol.Add("           SELECT  " & Mid(mFile.GetAttribute("FILENAME") + Space(20), 1, 20) & "ASSIGN  TO  " & mFile.GetAttribute("FILENAME") & ".")
                    End If
                End If
            Next
        End If
        Return strCobol
    End Function
    ''' <summary>
    ''' 获得语法树的XML节点
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetXMLElement() As System.Xml.XmlElement
        Dim mRootElement As XmlElement
        mRootElement = mXmlDocument.CreateElement("ENVIRONMENT")
        For Each mFile As XmlElement In FileList
            mRootElement.AppendChild(mFile.Clone)
        Next
        Return mRootElement
    End Function
    ''' <summary>
    ''' 添加文件
    ''' </summary>
    ''' <param name="SyntaxNode"></param>
    ''' <remarks></remarks>
    Public Sub AddFile(ByVal SyntaxNode As System.Xml.XmlElement)
        FileList.Add(SyntaxNode)
    End Sub
End Class
''' <summary>
''' 手续部节点类
''' </summary>
''' <remarks></remarks>
Public Class ProcedureNode
    Inherits clsSyntaxNode
    ''' <summary>
    ''' 手续部节列表
    ''' </summary>
    ''' <remarks></remarks>
    Public SectionList As New List(Of SectionNode)
    ''' <summary>
    ''' 主程序节
    ''' </summary>
    ''' <remarks></remarks>
    Public MainSection As New SectionNode With {.IsMainSection = True}
    ''' <summary>
    ''' 获得COBOL的代码
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function Convert2Cobol() As List(Of String)
        Dim strCobol As New List(Of String)
        strCobol.Add("       PROCEDURE                       DIVISION.")
        For Each Str As String In MainSection.Convert2Cobol
            strCobol.Add(Str)
        Next
        If SectionList.Count > 0 Then
            For Each secNode As SectionNode In SectionList
                For Each Str As String In secNode.Convert2Cobol
                    strCobol.Add(Str)
                Next
            Next
        End If
        '缩进重置
        Deepth = 1
        strCobol.Add(Space(LeftStart) & "INIT-PLI-RTN                   SECTION.".Replace("%prgid", Mid(clsJustifyStatement.LastModifyVarName(mIdentificationNode.ProgramID) & Space(20), 1, 20)))
        For Each StrLine As String In mDataNode.ActionList.Convert2Cobol
            strCobol.Add(StrLine)
        Next
        strCobol.Add(Space(LeftStart) & "INIT-PLI-RTN-EXIT.".Replace("%prgid", Mid(clsJustifyStatement.LastModifyVarName(mIdentificationNode.ProgramID) & Space(20), 1, 20)))
        strCobol.Add("          EXIT.")

        '@JRI  PROC 特殊处理 开始
        If mIdentificationNode.IsMain Then
            strCobol.Add("         @MAINED2.")
        Else
            strCobol.Add("         @SEND.")
        End If
        '@JRI  PROC 特殊处理 完了

        Return strCobol
    End Function
    ''' <summary>
    ''' 获得语法树的XML节点
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetXMLElement() As System.Xml.XmlElement
        Dim mRootElement As XmlElement
        mRootElement = mXmlDocument.CreateElement("PROCEDURE")
        MainSection.SectionName = "MAIN"
        mRootElement.AppendChild(MainSection.GetXMLElement)
        For Each sectionXml As SectionNode In SectionList
            mRootElement.AppendChild(sectionXml.GetXMLElement)
        Next
        Return mRootElement
    End Function
    ''' <summary>
    ''' 增加一个Section
    ''' </summary>
    ''' <param name="SecNode"></param>
    ''' <remarks></remarks>
    Public Sub AddSection(ByVal SecNode As SectionNode)
        SectionList.Add(SecNode)
    End Sub
End Class
''' <summary>
''' Section节点类
''' </summary>
''' <remarks>一个Section可以看做是一个程序块，所以其继承于StatementBlockNode</remarks>
Public Class SectionNode
    Inherits clsStatementBlock
    ''' <summary>
    ''' 过程名称
    ''' </summary>
    ''' <remarks></remarks>
    Public Property SectionName As String
    ''' <summary>
    ''' 是否为主过程
    ''' </summary>
    ''' <remarks></remarks>
    Public Property IsMainSection As String
    ''' <summary>
    ''' 过程内部定义的私有变量
    ''' </summary>
    ''' <remarks></remarks>
    Public Property DataList As New List(Of XmlElement)
    ''' <summary>
    ''' 带有参数的过程所定义的私有变量
    ''' </summary>
    ''' <remarks></remarks>
    Property ParaList As New List(Of String)
    ''' <summary>
    ''' 获得COBOL的代码
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function Convert2Cobol() As List(Of String)
        Dim strCobol As New List(Of String)
        For Each CommentXML As XmlElement In CommentList
            strCobol.Add(FormatCOBOLComment(CommentXML.GetAttribute("TEXT")))
        Next
        '1）对于主程序的话，应该采用Stop Run来结束程序。
        '2）对于一个Section结束的话，都应该采用Exit。
        '3）对于子程序的结束的话，应该采用GOBACK来结束程序。
        If SectionName = "MAIN" Then
            '@JRI  PROC 特殊处理 开始
            If mIdentificationNode.IsMain Then
                strCobol.Add("          @MAINST2('%progid',AUTO)".Replace("%progid", clsJustifyStatement.LastModifyVarName(mIdentificationNode.ProgramID)))
            Else
                strCobol.Add("          @SUBST2('%progid',PARMXXXPTR)".Replace("%progid", clsJustifyStatement.LastModifyVarName(mIdentificationNode.ProgramID)))
            End If
            '@JRI  PROC 特殊处理 完了

            '纯正的COBOL开头
            'strCobol.Add("       %prgid                   SECTION.".Replace("%prgid", Mid(ModifyVarExpress(mIdentificationNode.ProgramID) & Space(20), 1, 20)))

            '缩进重置
            Deepth = 1
            For Each StrLine As String In MyBase.Convert2Cobol
                strCobol.Add(StrLine)
            Next

            '@JRI  PROC 特殊处理 开始
            If mIdentificationNode.IsMain Then
                strCobol.Add("          @MEND.")
            Else
                strCobol.Add("          @SUBED2.")
            End If
            '@JRI  PROC 特殊处理 完了
            '纯正的COBOL结尾
            'strCobol.Add("          STOP RUN.")
            'strCobol.Add("       %prgid-EXIT.".Replace("%prgid", ModifyVarExpress(mIdentificationNode.ProgramID)))
            'strCobol.Add("          EXIT.")
        Else
            strCobol.Add("       %prgid                   SECTION.".Replace("%prgid", Mid(clsJustifyStatement.ModifySectionName(SectionName, False) & Space(20), 1, 20)))
            '缩进重置
            Deepth = 1
            For Each StrLine As String In MyBase.Convert2Cobol
                strCobol.Add(StrLine)
            Next
            'strCobol.Add("          GOBACK.")
            strCobol.Add("       %prgid.".Replace("%prgid", clsJustifyStatement.ModifySectionName(SectionName, True)))
            strCobol.Add("          EXIT.")
        End If
        Return strCobol
    End Function
    ''' <summary>
    ''' 获得语法树的XML节点
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetXMLElement() As System.Xml.XmlElement
        Dim mRootElement As XmlElement
        mRootElement = mXmlDocument.CreateElement("SECTION")
        mRootElement.SetAttribute("SectionName", SectionName)

        'ParaList
        Dim mParaListElement As XmlElement
        mParaListElement = mXmlDocument.CreateElement("PARALIST")
        For Each mData As String In ParaList
            Dim mParaXml As XmlElement = mXmlDocument.CreateElement("PARA")
            mParaListElement.SetAttribute("NAME", mData)
            mParaListElement.AppendChild(mParaXml)
        Next
        mRootElement.AppendChild(mParaListElement)

        'Data
        Dim mWorkstageElement As XmlElement
        mWorkstageElement = mXmlDocument.CreateElement("DATA")
        For Each mData As XmlElement In DataList
            mWorkstageElement.AppendChild(mData)
        Next
        mRootElement.AppendChild(mWorkstageElement)

        'CommentList
        Dim mCommentElement As XmlElement
        mCommentElement = mXmlDocument.CreateElement("COMMENTLIST")
        For Each mComList As XmlElement In CommentList
            mCommentElement.AppendChild(mComList)
        Next
        mRootElement.AppendChild(mCommentElement)
        For Each oprXml As XmlElement In SingleStatementList
            Select Case oprXml.Name
                Case "IF", "SELECT", "LOOP"
                    mRootElement.AppendChild(BlockOprList(CInt(oprXml.GetAttribute("BLOCKINDEX"))).GetXMLElement)
                Case Else
                    mRootElement.AppendChild(oprXml)
            End Select
        Next
        Return mRootElement
    End Function
    ''' <summary>
    ''' 添加数据
    ''' </summary>
    ''' <param name="DataNode"></param>
    ''' <remarks></remarks>
    Public Sub AddData(ByVal DataNode As System.Xml.XmlElement)
        If IsMainSection Then
            '如果这个过程是主过程的话，将数据放入数据部中
            mDataNode.AddData(DataNode)
        Else
            DataList.Add(DataNode)
        End If
    End Sub
End Class


